WebTransport gebruiken

WebTransport is een API die bidirectionele client-serverberichten met lage latentie biedt. Lees meer over de use cases en hoe u feedback kunt geven over de toekomst van de implementatie.

Achtergrond

Wat is WebTransport?

WebTransport is een web-API die het HTTP/3- protocol gebruikt als bidirectioneel transport. Het is bedoeld voor tweerichtingscommunicatie tussen een webclient en een HTTP/3-server. Het ondersteunt het verzenden van gegevens zowel onbetrouwbaar via de datagram-API's als betrouwbaar via de streams-API's .

Datagrammen zijn ideaal voor het verzenden en ontvangen van gegevens waarvoor geen sterke leveringsgaranties nodig zijn. Individuele gegevenspakketten worden in grootte beperkt door de maximale transmissie-eenheid (MTU) van de onderliggende verbinding en kunnen al dan niet succesvol worden verzonden. Als ze wel worden verzonden, kunnen ze in een willekeurige volgorde aankomen. Deze kenmerken maken de datagram-API's ideaal voor gegevensoverdracht met lage latentie en een optimale inspanning. Je kunt datagrammen zien als UDP-berichten (User Datagram Protocol) , maar dan versleuteld en met congestiecontrole.

De streams-API's daarentegen bieden betrouwbare , geordende gegevensoverdracht. Ze zijn zeer geschikt voor scenario's waarin u een of meer geordende datastromen moet verzenden of ontvangen. Het gebruik van meerdere WebTransport-stromen is vergelijkbaar met het opzetten van meerdere TCP- verbindingen, maar omdat HTTP/3 het lichtere QUIC- protocol onder de motorkap gebruikt, kunnen ze zonder veel overhead worden geopend en gesloten.

Gebruiksscenario's

Dit is een korte lijst met mogelijke manieren waarop ontwikkelaars WebTransport kunnen gebruiken.

  • Het met regelmatige tussenpozen en met minimale latentie versturen van de spelstatus naar een server via kleine, onbetrouwbare, niet-geordende berichten.
  • Het ontvangen van mediastreams die met minimale latentie vanaf een server worden gepusht, onafhankelijk van andere gegevensstromen.
  • Het ontvangen van meldingen die door een server worden gepusht terwijl een webpagina geopend is.

Wij willen graag meer weten over hoe u WebTransport gaat gebruiken.

Browserondersteuning

Browser Support

  • Chroom: 97.
  • Rand: 97.
  • Firefox: 114.
  • Safari: niet ondersteund.

Source

Zoals met alle functies die niet door universele browsers worden ondersteund, is het verstandig om defensief te coderen via functiedetectie .

Huidige status

Stap Status
1. Maak een uitleg Compleet
2. Maak een eerste ontwerp van de specificatie Compleet
3. Verzamel feedback en herhaal het ontwerp Compleet
4. Oorsprongsproef Compleet
5. Lancering Chroom 97

De relatie van WebTransport met andere technologieën

Is WebTransport een vervanging voor WebSockets?

Misschien. Er zijn toepassingsgevallen waarbij WebSockets of WebTransport geldige communicatieprotocollen kunnen zijn.

WebSockets-communicatie is gemodelleerd rond een enkele, betrouwbare, geordende berichtenstroom, wat prima is voor sommige communicatiebehoeften. Als u deze kenmerken nodig hebt, kunnen de streams API's van WebTransport deze ook bieden. Ter vergelijking: de datagram-API's van WebTransport bieden levering met lage latentie, zonder garanties over betrouwbaarheid of volgorde, en zijn daarom geen directe vervanging voor WebSockets.

Door WebTransport te gebruiken, via de datagram-API's of via meerdere gelijktijdige Streams API-instanties, hoeft u zich geen zorgen te maken over head-of-line-blokkering , wat een probleem kan zijn met WebSockets. Bovendien zijn er prestatievoordelen bij het opzetten van nieuwe verbindingen, omdat de onderliggende QUIC-handshake sneller is dan het opstarten van TCP via TLS.

WebTransport maakt deel uit van een nieuwe conceptspecificatie en daardoor is het WebSocket-ecosysteem rond client- en serverbibliotheken momenteel veel robuuster. Als u iets nodig hebt dat direct werkt met gangbare serverconfiguraties en brede webclientondersteuning biedt, zijn WebSockets vandaag de dag een betere keuze.

Is WebTransport hetzelfde als een UDP Socket API?

Nee. WebTransport is geen UDP Socket API . Hoewel WebTransport HTTP/3 gebruikt, wat op zijn beurt UDP "onder de motorkap" gebruikt, stelt WebTransport eisen aan encryptie en congestiecontrole, waardoor het meer is dan een standaard UDP Socket API.

Is WebTransport een alternatief voor WebRTC-datakanalen?

Ja, voor client-serververbindingen. WebTransport deelt veel van dezelfde eigenschappen als WebRTC-datakanalen , hoewel de onderliggende protocollen verschillen.

Over het algemeen vereist het runnen van een HTTP/3-compatibele server minder installatie en configuratie dan het onderhouden van een WebRTC-server, waarbij kennis van meerdere protocollen ( ICE , DTLS en SCTP ) vereist is om een ​​werkend transport te verkrijgen. WebRTC vereist veel meer bewegende onderdelen, wat kan leiden tot mislukte client/server-onderhandelingen.

De WebTransport API is ontworpen met de use cases van webontwikkelaars in gedachten en zou meer moeten aanvoelen als het schrijven van moderne webplatformcode dan als het gebruiken van de datakanaalinterfaces van WebRTC. In tegenstelling tot WebRTC wordt WebTransport ondersteund binnen Web Workers , waardoor u client-servercommunicatie onafhankelijk van een bepaalde HTML-pagina kunt uitvoeren. Omdat WebTransport een Streams -compatibele interface beschikbaar stelt, ondersteunt het optimalisaties rondom backpressure .

Als u echter al over een werkende WebRTC client/server-opstelling beschikt en daar tevreden mee bent, biedt de overstap naar WebTransport mogelijk niet veel voordelen.

Probeer het eens

De beste manier om met WebTransport te experimenteren is door een compatibele HTTP/3-server op te starten. Vervolgens kunt u deze pagina gebruiken met een eenvoudige JavaScript-client om client-servercommunicatie uit te proberen.

Daarnaast is er een door de community onderhouden echo-server beschikbaar op webtransport.day .

De API gebruiken

WebTransport is ontworpen op basis van moderne webplatformprimitieven, zoals de Streams API . Het is sterk afhankelijk van promises en werkt goed met async en await .

De huidige WebTransport-implementatie in Chromium ondersteunt drie verschillende typen verkeer: datagrammen en unidirectionele en bidirectionele stromen.

Verbinding maken met een server

U kunt verbinding maken met een HTTP/3-server door een WebTransport instantie aan te maken. Het schema van de URL moet https zijn. U moet het poortnummer expliciet opgeven.

Gebruik de ready promise om te wachten tot de verbinding tot stand is gebracht. Deze promise wordt pas nageleefd nadat de installatie is voltooid en wordt afgewezen als de verbinding in de QUIC/TLS-fase mislukt.

De closed belofte wordt vervuld als de verbinding normaal sluit, en afgewezen als de sluiting onverwacht was.

Als de server de verbinding afwijst vanwege een indicatiefout van de client (bijvoorbeeld het pad van de URL is ongeldig), dan zorgt dat ervoor dat closed wordt afgewezen, terwijl ready onopgelost blijft.

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

Datagram-API's

Zodra u een WebTransport-exemplaar hebt dat is verbonden met een server, kunt u dit gebruiken om afzonderlijke stukjes data, ook wel datagrammen genoemd, te verzenden en ontvangen.

De writeable getter retourneert een WritableStream , waarmee een webclient gegevens naar de server kan sturen. De readable getter retourneert een ReadableStream , waarmee u kunt luisteren naar gegevens van de server. Beide stromen zijn inherent onbetrouwbaar, dus het is mogelijk dat de gegevens die u schrijft niet door de server worden ontvangen, en vice versa.

Beide typen streams gebruiken Uint8Array instanties voor gegevensoverdracht.

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

Streams API's

Nadat u verbinding hebt gemaakt met de server, kunt u WebTransport ook gebruiken om gegevens te verzenden en ontvangen via de Streams API's.

Elk deel van alle streams is een Uint8Array . In tegenstelling tot de Datagram API's zijn deze streams betrouwbaar. Maar elke stream is onafhankelijk, dus de volgorde van de gegevens over de streams is niet gegarandeerd.

WebTransportSendStream

Een WebTransportSendStream wordt door de webclient gemaakt met behulp van de createUnidirectionalStream() -methode van een WebTransport exemplaar, dat een promise voor de WebTransportSendStream retourneert.

Gebruik de close() -methode van de WritableStreamDefaultWriter om de bijbehorende HTTP/3-stream te sluiten. De browser probeert alle in behandeling zijnde gegevens te verzenden voordat de bijbehorende stream daadwerkelijk wordt gesloten.

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

Gebruik op dezelfde manier de abort() -methode van de WritableStreamDefaultWriter om een RESET_STREAM naar de server te sturen. Bij gebruik van abort() kan de browser alle in behandeling zijnde gegevens die nog niet zijn verzonden, negeren.

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

Een WebTransportReceiveStream wordt geïnitieerd door de server. Het verkrijgen van een WebTransportReceiveStream is een proces in twee stappen voor een webclient. Eerst wordt het kenmerk incomingUnidirectionalStreams van een WebTransport instantie aangeroepen, wat een ReadableStream retourneert. Elk deel van die ReadableStream is op zijn beurt een WebTransportReceiveStream die kan worden gebruikt om Uint8Array instanties te lezen die door de server zijn verzonden.

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

U kunt streamsluiting detecteren met behulp van de closed belofte van ReadableStreamDefaultReader . Wanneer de onderliggende HTTP/3-stream wordt gesloten met de FIN-bit , wordt de closed belofte vervuld nadat alle gegevens zijn gelezen. Wanneer de HTTP/3-stream abrupt wordt gesloten (bijvoorbeeld door RESET_STREAM ), wordt de closed belofte afgewezen.

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectioneleStream

Een WebTransportBidirectionalStream kan door de server of de client worden gemaakt.

Webclients kunnen er een maken met de createBidirectionalStream() -methode van een WebTransport exemplaar, dat een promise retourneert voor een WebTransportBidirectionalStream .

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

U kunt luisteren naar een WebTransportBidirectionalStream die door de server is aangemaakt met het kenmerk incomingBidirectionalStreams van een WebTransport instantie, die een ReadableStream retourneert. Elk deel van die ReadableStream is op zijn beurt een WebTransportBidirectionalStream .

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

Een WebTransportBidirectionalStream is gewoon een combinatie van een WebTransportSendStream en WebTransportReceiveStream . De voorbeelden uit de vorige twee secties leggen uit hoe je ze allebei kunt gebruiken.

Meer voorbeelden

De WebTransport-conceptspecificatie bevat een aantal aanvullende inline-voorbeelden, samen met volledige documentatie voor alle methoden en eigenschappen.

WebTransport in DevTools van Chrome

Helaas ondersteunen de DevTools van Chrome momenteel geen WebTransport. U kunt dit Chrome-probleem markeren met een ster om op de hoogte te worden gehouden van updates in de DevTools-interface.

Polyfill

Er is een polyfill (of liever ponyfill die functionaliteit biedt als een zelfstandige module die u kunt gebruiken) beschikbaar, genaamd webtransport-ponyfill-websocket die enkele functies van WebTransport implementeert. Lees de beperkingen in de README van het project zorgvuldig door om te bepalen of deze oplossing geschikt is voor uw toepassing.

Overwegingen met betrekking tot privacy en beveiliging

Zie het overeenkomstige gedeelte van het ontwerp van de specificatie voor gezaghebbende richtlijnen.

Feedback

Het Chrome-team wil graag uw mening en ervaringen horen over het gebruik van deze API.

Feedback over het API-ontwerp

Is er iets aan de API dat niet helemaal klopt of niet werkt zoals verwacht? Of ontbreken er onderdelen die je nodig hebt om je idee te implementeren?

Dien een probleem in op de Web Transport GitHub-repository of voeg uw mening toe over een bestaand probleem.

Probleem met de implementatie?

Heb je een bug gevonden in de implementatie van Chrome?

Meld een bug op https://new.crbug.com . Geef zoveel mogelijk details en eenvoudige instructies voor reproductie.

Wilt u de API gebruiken?

Met uw openbare steun kan Chrome prioriteit geven aan bepaalde functies en laat u andere browserleveranciers zien hoe belangrijk het is om deze functies te ondersteunen.

Algemene discussie

Voor algemene vragen of problemen die niet in een van de andere categorieën passen, kunt u de Google-groep web-transport-dev gebruiken.

Dankbetuigingen

Dit artikel bevat informatie uit de WebTransport Explainer , de conceptspecificatie en gerelateerde ontwerpdocumentatie . Dank aan de respectievelijke auteurs voor het aanleveren van deze basis.

De hoofdafbeelding bij dit bericht is van Robin Pierre op Unsplash.